import { WSClient } from '../core/ws-client';
import { TickerData } from '../core/types';
export class PublicService {
    private wsClient: WSClient;
    private defaultTimeout = 15000; // 默认超时时间：15秒

    constructor(client: WSClient) {
        this.wsClient = client;
    }

    /**
     * 订阅产品信息频道
     * @param instType 产品类型，如 'SPOT', 'FUTURES'
     * @param onInstrumentsUpdate 接收到产品信息更新时调用的回调函数
     * @param timeout 可选：超时时间（毫秒）
     * @returns Promise，在订阅成功或失败时解析
     */
    public subscribeInstruments(
        instType: string,
        onInstrumentsUpdate: (data: any) => void,
        timeout: number = this.defaultTimeout
    ): Promise<void> {
        return new Promise((resolve, reject) => {
            // 确保WebSocket已连接
            if (!this.wsClient.isConnected()) {
                reject(new Error("WebSocket is not connected"));
                return;
            }

            const channel = 'instruments';

            // 设置超时
            const subscribeTimeout = setTimeout(() => {
                this.wsClient.off('subscribeSuccess', subscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error(`Subscribe to ${channel} timeout after ${timeout}ms`));
            }, timeout);

            // 注册回调函数
            this.wsClient.on(channel, onInstrumentsUpdate);

            // 监听订阅成功事件
            const subscribeSuccessHandler = (response: any) => {
                if (response.arg?.channel === channel) {
                    clearTimeout(subscribeTimeout);
                    resolve();
                }
            };

            // 监听错误事件
            const errorHandler = (err: any) => {
                clearTimeout(subscribeTimeout);
                if (err.message?.includes(channel) || err.code) {
                    reject(err);
                }
            };

            this.wsClient.once('subscribeSuccess', subscribeSuccessHandler);
            this.wsClient.once('error', errorHandler);

            // 发送订阅请求
            const subscribeSuccess = this.wsClient.subscribe(channel, instType);
            if (!subscribeSuccess) {
                clearTimeout(subscribeTimeout);
                this.wsClient.off('subscribeSuccess', subscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error("Failed to send subscription request"));
            }
        });
    }

    /**
     * 取消订阅产品信息
     * @param instType 产品类型
     * @param timeout 可选：超时时间（毫秒）
     * @returns Promise，在取消订阅成功或失败时解析
     */
    public unsubscribeInstruments(
        instType: string,
        timeout: number = this.defaultTimeout
    ): Promise<void> {
        return new Promise((resolve, reject) => {
            const channel = 'instruments';

            // 设置超时
            const unsubscribeTimeout = setTimeout(() => {
                this.wsClient.off('unsubscribeSuccess', unsubscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error(`Unsubscribe from ${channel} timeout after ${timeout}ms`));
            }, timeout);

            // 监听取消订阅成功事件
            const unsubscribeSuccessHandler = (response: any) => {
                if (response.arg?.channel === channel) {
                    clearTimeout(unsubscribeTimeout);
                    this.wsClient.removeAllListeners(channel);
                    resolve();
                }
            };

            // 监听错误事件
            const errorHandler = (err: any) => {
                clearTimeout(unsubscribeTimeout);
                if (err.message?.includes(channel) || err.code) {
                    reject(err);
                }
            };

            this.wsClient.once('unsubscribeSuccess', unsubscribeSuccessHandler);
            this.wsClient.once('error', errorHandler);

            // 发送取消订阅请求
            const unsubscribeSuccess = this.wsClient.unsubscribe(channel, instType);
            if (!unsubscribeSuccess) {
                clearTimeout(unsubscribeTimeout);
                this.wsClient.off('unsubscribeSuccess', unsubscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error("Failed to send unsubscription request"));
            }
        });
    }

    /**
     * 订阅行情数据
     * @param instId 产品ID，如"BTC-USDT"
     * @param onTickerUpdate 当接收到最新行情数据时调用的回调函数
     * @param timeout 可选：超时时间（毫秒）
     * @returns Promise，在订阅成功或失败时解析
     */
    public subscribeTicker(
        instId: string,
        onTickerUpdate: (data: TickerData[]) => void,
        timeout: number = this.defaultTimeout
    ): Promise<void> {
        return new Promise((resolve, reject) => {
            // 确保WebSocket已连接
            if (!this.wsClient.isConnected()) {
                reject(new Error("WebSocket is not connected"));
                return;
            }

            const channel = 'tickers';

            // 设置超时
            const subscribeTimeout = setTimeout(() => {
                this.wsClient.off('subscribeSuccess', subscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error(`Subscribe to ${channel} timeout after ${timeout}ms`));
            }, timeout);

            // 注册回调函数，处理ticker数据的消息
            const eventName = `${channel}:${instId}`;
            this.wsClient.on(eventName, onTickerUpdate);

            // 监听订阅成功事件
            const subscribeSuccessHandler = (response: any) => {
                if (response.arg?.channel === channel && response.arg?.instId === instId) {
                    clearTimeout(subscribeTimeout);
                    resolve();
                }
            };

            // 监听错误事件
            const errorHandler = (err: any) => {
                clearTimeout(subscribeTimeout);
                if (err.message?.includes(channel) || err.code) {
                    reject(err);
                }
            };

            this.wsClient.once('subscribeSuccess', subscribeSuccessHandler);
            this.wsClient.once('error', errorHandler);

            // 发送订阅请求
            const subscribeSuccess = this.wsClient.subscribe(channel, instId);
            if (!subscribeSuccess) {
                clearTimeout(subscribeTimeout);
                this.wsClient.off('subscribeSuccess', subscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error("Failed to send subscription request"));
            }
        });
    }

    /**
     * 取消订阅行情数据
     * @param instId 产品ID，如"BTC-USDT"
     * @param timeout 可选：超时时间（毫秒）
     * @returns Promise，在取消订阅成功或失败时解析
     */
    public unsubscribeTicker(
        instId: string,
        timeout: number = this.defaultTimeout
    ): Promise<void> {
        return new Promise((resolve, reject) => {
            const channel = 'tickers';

            // 设置超时
            const unsubscribeTimeout = setTimeout(() => {
                this.wsClient.off('unsubscribeSuccess', unsubscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error(`Unsubscribe from ${channel} timeout after ${timeout}ms`));
            }, timeout);

            // 监听取消订阅成功事件
            const unsubscribeSuccessHandler = (response: any) => {
                if (response.arg?.channel === channel && response.arg?.instId === instId) {
                    clearTimeout(unsubscribeTimeout);

                    // 移除相关的事件监听器
                    const eventName = `${channel}:${instId}`;
                    this.wsClient.removeAllListeners(eventName);

                    resolve();
                }
            };

            // 监听错误事件
            const errorHandler = (err: any) => {
                clearTimeout(unsubscribeTimeout);
                if (err.message?.includes(channel) || err.code) {
                    reject(err);
                }
            };

            this.wsClient.once('unsubscribeSuccess', unsubscribeSuccessHandler);
            this.wsClient.once('error', errorHandler);

            // 发送取消订阅请求
            const unsubscribeSuccess = this.wsClient.unsubscribe(channel, instId);
            if (!unsubscribeSuccess) {
                clearTimeout(unsubscribeTimeout);
                this.wsClient.off('unsubscribeSuccess', unsubscribeSuccessHandler);
                this.wsClient.off('error', errorHandler);
                reject(new Error("Failed to send unsubscription request"));
            }
        });
    }
} 